package com.superafroman.utils.scanner.criteria;

import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.objectweb.asm.ClassReader;

import com.superafroman.asm.ClassAnnotationCollector;

/**
 * {@link IClassCriteria} used to check if a class has a specific
 * {@link Annotation}.
 */
public class ClassAnnotationCriteria implements IClassCriteria {

    private static final Log LOG = LogFactory.getLog(ClassAnnotationCriteria.class);

    private String annotation;

    public ClassAnnotationCriteria(Class<?> annotation) {
        if (annotation == null) {
            throw new NullPointerException("annotation cannot be null");
        }

        this.annotation = "L" + annotation.getCanonicalName().replace(".", "/") + ";";
    }

    /**
     * {@inheritDoc}
     */
    public boolean fitsCriteria(String className, InputStream classInputStream) {

        try {
            ClassAnnotationCollector collector = new ClassAnnotationCollector();

            ClassReader reader = new ClassReader(classInputStream);
            reader.accept(collector, ClassReader.SKIP_DEBUG
                    | ClassReader.SKIP_CODE | ClassReader.SKIP_FRAMES);

            List<String> annotations = collector.getAnnotations();
            for (String annotation : annotations) {
                if (this.annotation.equals(annotation)) {
                    return true;
                }
            }
        } catch (Exception e) {
            LOG.error("Exception scanning class for annotation '" + annotation
                    + "'.", e);
        }

        return false;
    }
}
